package com.simple.common.entity.po.sys;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.simple.common.framework.context.Contexts;
import com.simple.common.framework.scale.Scale;
import lombok.Data;
import lombok.SneakyThrows;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.sql.Time;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 所有金额注意使用scale 格式话小数点后两位
 *
 * @author yasud
 * @date 2020年09月22日 15:44
 * @description
 */
@Data
public class Trade extends BaseEntity2 {

    /**
     * 商户订单编号
     */
    private String merchantOrderNo;

    /**
     * 渠道订单编号
     */
    private String channelOrderNo;

    /**
     * 订单金额
     */
    private String amount;

    /**
     * 币种
     */
    private String currency;

    /**
     * 汇率转化后订单金额，未加点
     */
    private String convertOrderAmount;

    /**
     * 汇率转化后订单币种,
     */
    private String convertOrderCurrency;

    /**
     * 实际支付金额，渠道服务传给渠道的实际支付金额
     */
    private String payAmount;

    /**
     * 实际支付币种，渠道服务传给渠道实际支付币种
     */
    private String payAmountCurrency;

    /**
     * 商户号
     */
    private String merchantNo;

    /**
     * 商户名称
     */
    private String merchantName;

    /**
     * 关联商户
     */
    private Merchant merchant;

    /**
     * 关联applicationId
     */
    private Long applicationId;

    /**
     * 应用名称
     */
    private String applicationName;

    /**
     * 关联application 类型
     */
    private Application.Type applicationType;

    /**
     *
     */
    private Application application;

    /**
     * 实例的appId
     */
    private String appId;

    /**
     * 实例名称
     */
    private String appName;

    /**
     * 关联实例
     */
    private AppExample example;

    /**
     * 管理产品Id
     */
    private Long productId;

    /**
     * 关联产品名称
     */
    private String productName;

    /**
     * 渠道商户id
     */
    private Long channelMerchantId;

    /**
     * 渠道商户名称
     */
    private String channelMerchantName;

    /**
     * 实例渠道id
     */
    private Long expChannelId;

    /**
     * 关联产品
     */
    private Product product;

    /**
     * 订单状态
     */
    private Status status;
    /**
     * 订单类型
     */
    private Type type;

    /**
     * 争议状态
     */
    private DisputeStatus disputeStatus;

    /**
     * 状态消息
     */
    private String msg;

    /**
     * 渠道返回的订单状态
     */
    private String channelStatus;

    /**
     * 渠道返回的消息
     */
    private String channelMsg;

    /**
     * 退款状态
     */
    private RefundStatus refundStatus;

    /**
     * 已退总金额
     */
    private String refundAmount;

    /**
     * 支付日期
     */
    private String ymd;

    /**
     * 支付时间
     */
    private Time time;

    /**
     * 支付完成时间
     */
    private Date completeTime;

    /**
     * 渠道code
     */
    private String channelCode;

    /**
     * 渠道名称
     */
    private Long channelId;

    /**
     * 渠道名称
     */
    private String channelName;

    /**
     * 每笔订单描述
     */
    private String orderDesc;

    /**
     * 异步通知地址
     */
    private String asyncUrl;

    /**
     * 同步跳转地址
     */
    private String syncUrl;

    /**
     * 请求信息，一般是，请求对象的extra 的内容
     */
    private String extraInfo;

    /**
     * 订单消息
     */
    private String billingInfo;

    /**
     * 商品信息
     */
    private String goodsList;

    /**
     * 消费信息
     */
    private String shippingInfo;

    /**
     * 信用卡持有人
     */
    private String cardHolder;

    /**
     * 信用卡过期年
     */
    private String cardExYear;

    /**
     * 信用卡过期月
     */
    private String cardExMonth;

    /**
     * 信用卡CVV
     */
    private String cardCvv;

    /**
     * 信用卡卡号
     */
    private String cardNo;

    /**
     * 备注字段 这个字段是最大的一个，可以存json, 一般来说就是存和渠道交易的时候产生的临时信息
     */
    private String remark1;

    /**
     * 备注字段2
     */
    private String remark2;

    /**
     * 备注字段3
     */
    private String remark3;
    /**
     * 代付方式
     */
    private WithdrawalType withdrawalType;
    /**
     * 收款人姓名
     */
    private String accName;
    /**
     * 收款账号
     */
    private String accNumber;
    /**
     * 审核状态
     */
    private AuditStatus auditStatus;
    /**
     * 最终审核时间
     */
    private Date endAuditTime;
    /**
     * 发起人
     */
    private String originator;

    /**
     * 订单类型
     */
    public enum WithdrawalType {

        /**
         * 无用
         */
        NONE,
        /**
         * 私账  -- 国内
         */
        PRIVATE_ACCOUNT,

        /**
         * 公账 -- 国内
         */
        PUBLIC_ACCOUNT,
        /**
         * 银行账户 --尼日利亚银行
         */
        BANK,
         /**
         * opay钱包 -- 尼日利亚
         */
         OPAY,
         /**
         * IMPS -- 印度银行
         */
        IMPS,
         /**
         * UPI -- 印度upi
         */
         UPI,
         /**
         * PAYTM -- 印度paytm
         */
        PAYTM,
         /**
         * 银行代付	 -- 越南代付
         */
         VIETNAMBANK
    }

    /**
     * 代付审核状态
     */
    public enum AuditStatus {

        /**
         * 审核中
         */
        AUDIT_PROCESS,

        /**
         * 审核成功
         */
        AUDIT_SUCCESS,
        /**
         * 审核失败
         */
        AUDIT_FAILURE,
        /**
         * 初审成功
         */
        FRIST_AUDIT_SUCCESS,
        /**
         * 初审失败
         */
        FRIST_AUDIT_FAILURE
    }

    /**
     * 订单类型
     */
    public enum Type {

        /**
         * 普通订单
         */
        NORMAL_TRADE,

        /**
         * 商户费用订单
         */
        MERCHANT_FEE_TRADE,
        /**
         * 渠道费用订单
         */
        CHANNEL_FEE_TRADE,
        /**
         * 支付订单
         */
        NORMAL_TRADE_PAY,
        /**
         * 代付订单
         */
        NORMAL_TRADE_WITHDRAWAL
    }


    /**
     * 订单状态
     */
    public enum Status {
        /**
         * 订单已受理
         */
        ACCEPT,

        /**
         * 支付中
         */
        PENDING,

        /**
         * 支付成功
         */
        SUCCESS,

        /**
         * 支付失败
         */
        FAILED;
    }

    /**
     * 订单退款状态
     */
    public enum RefundStatus {

        /**
         * 没有退款
         */
        NONE,

        /**
         * 部分退款
         */
        REFUND_PART,

        /**
         * 全部退款
         */
        REFUND_FULL
    }

    @SneakyThrows
    public Map<String, Object> remark1Map() {
        ObjectMapper objectMapper = Contexts.OBJECTMAPPER;
        if (StringUtils.isBlank(remark1)) {
            remark1 = "{}";
        }
        Map map = objectMapper.readValue(remark1, Map.class);
        return map;
    }

    /**
     * 放一个值
     *
     * @param key
     * @param value
     * @return
     */
    @SneakyThrows
    public Map<String, Object> putToRemark1(String key, Object value) {
        Map<String, Object> map = remark1Map();
        ObjectMapper objectMapper = Contexts.OBJECTMAPPER;
        map.put(key, value);
        setRemark1(objectMapper.writeValueAsString(map));
        return map;
    }

    /**
     * 放所有值
     *
     * @param add
     * @return
     */
    @SneakyThrows
    public Map<String, Object> putAllToRemark1(Map<String, Object> add) {
        Map<String, Object> map = remark1Map();
        ObjectMapper objectMapper = Contexts.OBJECTMAPPER;
        map.putAll(add);
        setRemark1(objectMapper.writeValueAsString(map));
        return map;
    }

    /**
     * 返回给定的字符串形式
     *
     * @param key
     * @return
     */
    @JsonIgnore
    public String getAsString(String key) {
        return (String) remark1Map().get(key);
    }

    /**
     * 返回给定key的 bigdecimal
     *
     * @param key
     * @return
     */
    @JsonIgnore
    public BigDecimal getAsBigDecimal(String key) {
        return (BigDecimal) remark1Map().get(key);
    }

    /**
     * 返回给定int
     *
     * @param key
     * @return
     */
    @JsonIgnore
    public Integer getAsInt(String key) {
        return (Integer) remark1Map().get(key);
    }

    /**
     * 给定列表
     *
     * @param key
     * @return
     */
    @JsonIgnore
    public List getAsList(String key) {
        return (List) remark1Map().get(key);
    }

    /**
     * 给定 map
     *
     * @param key
     * @return
     */
    @JsonIgnore
    public Map getAsMap(String key) {
        return (Map) remark1Map().get(key);
    }


    @SneakyThrows
    public <R> R getFromExtra(String key) {
        Map<String, Object> map = Contexts.OBJECTMAPPER.readValue(extraInfo, Map.class);
        R r = (R) map.get(key);
        return r;
    }

    /**
     * 增加值
     *
     * @param refundAmount
     */
    public void addRefundAmount(String refundAmount) {
        this.refundAmount = Scale.scale(new BigDecimal(ObjectUtils.defaultIfNull(this.refundAmount, "0")).add(new BigDecimal(refundAmount))).toString();
    }

    public enum DisputeStatus {
        PROCESS,
        APPEAL_SUCCESS,
        APPEAL_FAILED,
        APPROVAL
    }
}
